<?php defined('SYSPATH') or die('No direct script access.');

class Model_ShopParser_Admitad extends Model_ShopParser_Abstract
{ 
    protected $filename = null;         // Название файла
    protected $handler = null;          // Дескриптор файла
    protected $charset = null;          // Кодировка входного файла
    
    public function parse($url, $allow_cashback = true)
    {  
        //$this->filename = APPPATH.'../data/tmp/admitad_shops.xml';  
        $this->filename = APPPATH.'../data/tmp/'.time().'_'.mt_rand(1, 1000).'.xml';
        $this->_download_file($url, $this->filename);
        $n = $this->_parse($allow_cashback);
        unlink($this->filename); 
        
        return $n;
    }    
    
    protected function _parse($allow_cashback = true)
    {
        $this->_add_nl_to_offers();
        $this->_open_file();   
        $this->_detect_charset();
        
        $n = 0;
        $current_id = $this->_get_current_shop_id();
        
        // Добавляем магазины
        while ($shop_data = $this->_get_shop()) {
            $shop_partner       = 'admitad';                        
            $shop_source_id     = $this->_get_shop_id($shop_data);
            
            $shop = ORM::factory('shop')
                        ->where('partner', '=', $shop_partner)
                        ->where('source_id', '=', $shop_source_id)
                        ->find();
            if ($shop->loaded() && $shop->gotolink) {
                continue;    
            }
                        
            $shop_category      = $this->_get_shop_category($shop_data);
            $shop_subcategory   = $this->_get_shop_subcategory($shop_data);
            $shop_name          = $this->_get_shop_name($shop_data); 
            $shop_url           = Model_Main::translit($shop_name);
            $shop_url           = str_replace('-amp-', '-and-', $shop_url);
            $shop_site          = $this->_get_shop_site($shop_data);         
            $shop_gotolink      = $this->_get_shop_gotolink($shop_data);
            $shop_logo          = $this->_get_shop_logo($shop_data);
            $shop_geotargeting  = $this->_get_shop_geotargeting($shop_data); 
            $shop_postclick_cookie = $this->_get_shop_postclick_cookie($shop_data);
            $shop_currency      = $this->_get_shop_currency($shop_data);
            
            $shop_actions       = $this->_get_shop_actions($shop_data);   
            
            $payment_size       = $this->_get_shop_payment_size($shop_actions);
            $client_payment_size = $this->_get_shop_client_payment_size($shop_actions);
            $percentage         = $this->_get_shop_payment_percentage($shop_actions);
            $hold_time          = $this->_get_shop_hold_time($shop_actions);
            
            try { 
                $current_id++;
                
                echo '<pre>';
                echo "INSERT INTO shops (id, partner, source_id, name, url) VALUES ($current_id, '$shop_partner', $shop_source_id, '$shop_name', '$shop_url');<br />";
                $cashback = '';
                if ($allow_cashback) {
                    $cashback = "cashback_payment_size = '$client_payment_size', ";    
                }                          
                echo "UPDATE shops SET site = '$shop_site', gotolink = '$shop_gotolink', logo = '$shop_logo', geotargeting = '$shop_geotargeting', postclick_cookie = $shop_postclick_cookie, currency = '$shop_currency', payment_size = '$payment_size', {$cashback}recommend_payment_size = '$client_payment_size', percentage = $percentage, hold_time = '$hold_time' WHERE id = $current_id;<br />";                                                                                        
                foreach ($shop_actions as $action) {
                    $cashback_name = $cashback_value = '';
                    if ($allow_cashback) {
                        $cashback_name  = 'cashback_payment_size, ';
                        $cashback_value = "{$action['client_payment_size']}, ";    
                    }
                    echo "INSERT INTO actions (shop_id, name, payment_size, {$cashback_name}recommend_payment_size, percentage, hold_time) VALUES ";
                    echo "($current_id, '{$action['name']}', {$action['payment_size']}, {$cashback_value}{$action['client_payment_size']}, {$action['percentage']}, {$action['hold_time']});<br />";
                }
                echo '<br /><br />';

                //DB::insert('shops', array('id', 'name', 'site', 'url'))
                //        ->values(array($shop_id, $shop_name, $shop_site, $shop_url))->execute();
            } catch (Database_Exception $e) {
                if (strstr($e->getMessage(), 'Duplicate entry') !== false) {
                    continue;
                }
                die($e->getMessage());
            } 
                  
        }
        
        //echo 'UPDATE shops SET category_id = (SELECT id FROM categories WHERE name = shops.category)';
            
        $this->_close_file(); 
        return $n;     
    }       
    
    /*protected function _get_category_id(&$category_data)
    {
        $category_id = $this->_cut_str('id="', '"', $category_data);
        return $category_id;  
    }
    
    protected function _get_category_name(&$category_data)
    {
        $name = $this->_cut_str('>', '<', $category_data);
        return $this->_cut_quotes($name);  
    }
    
    protected function _get_category_parent_id(&$category_data)
    {
        $parent_id = $this->_cut_str('parentId="', '"', $category_data);
        if (!$parent_id) {
            return 0;
        }
        return $parent_id;  
    } */
    
    protected function _get_shop_id(&$shop_data)
    {
        $shop_id = $this->_cut_str('<id>', '</id>', $shop_data); 
        return (int)$shop_id;   
    }
    
    protected function _get_shop_category(&$shop_data)
    {
        return $this->_cut_str('<category>', '</category>', $shop_data);    
    }
    
    protected function _get_shop_subcategory(&$shop_data)
    {
        return $this->_cut_str('<subcategory>', '</subcategory>', $shop_data);    
    }
    
    protected function _get_shop_name($shop_data)
    {
        $name = $this->_cut_str('<name>', '</name>', $shop_data); 
        return $name;     
    }
    
    protected function _get_shop_site($shop_data)
    {
        $url = $this->_cut_str('<site_url>', '</site_url>', $shop_data); 
        return $url;     
    }
    
        protected function _get_shop_gotolink(&$shop_data)
    {
        return $this->_cut_str('<gotolink>', '</gotolink>', $shop_data);  
    } 
    
    protected function _get_shop_logo(&$shop_data)
    {
        return $this->_cut_str('<logo>', '</logo>', $shop_data);  
    }   
    
    protected function _get_shop_geotargeting(&$shop_data)
    {
        //return $this->_cut_str('<geotargeting>', '</geotargeting>', $shop_data); 
        
        $geo = array();
        while ($item_string = $this->_cut_str('<region>', '</region>', $shop_data)) {        
            $geo[] = $item_string;
        }     
        return implode(', ', $geo);
            
    }  
    
    protected function _get_shop_postclick_cookie(&$shop_data)
    {
        return $this->_cut_str('<postclick_cookie>', '</postclick_cookie>', $shop_data);    
    }  
    
    protected function _get_shop_currency(&$shop_data)
    {
        return $this->_cut_str('<currency_id>', '</currency_id>', $shop_data);     
    }  
    
    protected function _get_shop_actions(&$shop_data)
    {
        $actions = array();
        while ($item_string = $this->_cut_str('<action>', '</action>', $shop_data)) {
            $item = array();
            $item['source_id']      = $this->_cut_str('<id>', '</id>', $item_string);
            $item['name']           = $this->_cut_str('<name>', '</name>', $item_string);
            $item['payment_size']   = $this->_cut_str('<payment_size>', '</payment_size>', $item_string);
            $item['client_payment_size'] = $item['payment_size']/2;
            $item['percentage']     = $this->_cut_str('<percentage>', '</percentage>', $item_string); 
            $item['hold_time']      = $this->_cut_str('<hold_time>', '</hold_time>', $item_string); 
            
            $actions[] = $item;
        }     
        return $actions;
    } 
    
    protected function _get_shop_payment_size($shop_actions)
    {
        $min = $max = $shop_actions[0]['payment_size'];
        foreach ($shop_actions as $action) {
            if ($action['payment_size'] < $min) {
                $min = $action['payment_size'];    
            }
            if ($action['payment_size'] > $max) {
                $max = $action['payment_size'];    
            }    
        } 
        if ($min != $max) {
            return $min.'-'.$max;     // TODO percentage?    
        } 
        return $min; 
    }
    
    protected function _get_shop_client_payment_size($shop_actions)
    {
        $min = $max = $shop_actions[0]['client_payment_size'];
        foreach ($shop_actions as $action) {
            if ($action['client_payment_size'] < $min) {
                $min = $action['client_payment_size'];    
            }
            if ($action['client_payment_size'] > $max) {
                $max = $action['client_payment_size'];    
            }    
        } 
        if ($min != $max) {
            return $min.'-'.$max;     // TODO percentage?    
        } 
        return $min; 
    }
    
    protected function _get_shop_payment_percentage($shop_actions)
    {
        return $shop_actions[0]['percentage'];    
    }
    
    protected function _get_shop_hold_time($shop_actions)
    {
        $min = $max = $shop_actions[0]['hold_time'];
        foreach ($shop_actions as $action) {
            if ($action['hold_time'] < $min) {
                $min = $action['hold_time'];    
            }
            if ($action['hold_time'] > $max) {
                $max = $action['hold_time'];    
            }    
        } 
        if ($min != $max) {
            return $min.'-'.$max;  
        } 
        return $min;    
    }
    
    protected function _get_current_shop_id()
    {
        $current_id = DB::select(array(DB::expr('MAX(id)'), 'max'))
            ->from('shops')
            ->execute()
            ->as_array();
        $current_id = $current_id[0]['max'];
        return $current_id;
    }
    
    protected function _add_nl_to_offers()
    {
        $in_handler   = fopen($this->filename, 'r+');
        
        $out_filename = APPPATH.'../data/tmp/tmp'.time().'_'.mt_rand(0, 1000).'.xml';
        $out_handler  = fopen($out_filename, 'w+'); 
        
        while($str = fgets($in_handler)) {
            $str = str_replace('><', ">\r\n<", $str);
            fputs($out_handler, $str);    
        }
        
        unset($this->filename);
        $this->filename = $out_filename;
    }
    
    protected function _open_file()
    {
        $result = $this->handler = fopen($this->filename, 'r+'); 
        if (!$result) {
            throw new Model_Exception('Не удалось открыть файл');
        }
        return $result; 
    }
    
    protected function _detect_charset()
    {
        $str = fgets($this->handler);
        $charset = $this->_cut_str(' encoding="', '"', $str);
        
        if ($charset) {
            $this->charset = mb_strtolower($charset);
        } else {
            $this->charset = 'utf-8';
        }
    }
    
    protected function _encode($str)
    {
        if ($this->charset == 'utf-8') {
            return $str;
        }
        
        return iconv($this->charset, 'utf-8', $str);
    }
    
    protected function _get_shop()
    {
        $data = null;
        while($str = fgets($this->handler)) {  
            if (strstr($str, '</advcampaigns>') !== false) {
                return null;    
            }               
            if (strstr($str, '<advcampaign') !== false) {
                $data = $str;
                
                do {
                    $str   = fgets($this->handler);
                    $data .= $str;
                } while (strstr($str, '</advcampaign>') === false);
                //fseek($this->handler, -mb_strlen($str), SEEK_CUR);
                
                break;
            }
        }  
        return $this->_encode($data);   
    } 
    
    protected function _close_file()
    {
        if (!fclose($this->handler)) {
            throw new Model_Exception('Не удалось закрыть файл');   
        }  
        return true; 
    }
    
    protected function _cut_quotes($str)
    {
        return trim(str_replace(array('<![CDATA[', ']]>'), '', $str));    
    }
}